# aem.container
# Various convenient container-types for AEM codes
# Copyright (c) 2000,2001, Vic Kelson and Mark Bakker

import UserList
import copy
import geometry

class ColumnList(UserList.UserList):
	"""List of objects, treated as a column vector

	Contains a list of parameter values, type of data inferred from
	usage context. The list is used as a column vector"""
	def __mul__(self,value):
		raise "Invalid mathematical operation on ColumnList"


class RowList(UserList.UserList):
	"""List of object, treated as a row vector

	Contains a list of values often representing valules returned
	by influence functions, type of data inferred from usage context.
	The list is used as a row vector"""
	def __mul__(self,value):
		'''Overloaded multiplication row * column = scalar

		Vector multiplication of a row vector * column vector = scalar.
		Valid only for vectors of equal length.'''
		if isinstance(value,ColumnList):
			assert len(self) == len(value), "Length mismatch"
			return reduce(lambda x,y: x+y,
			              map(lambda x,y: x*y, self, value)
			              , 0
			             )
		# added a default value 0 (optional 3rd argument of reduce)
		# so that empty lists can be handled                          - wjz

class TraceCheck:
	'''Object for checking the position of a trace line

	Attributes:

	- change: logical set to 1 if new xyz has been modified
	- stop: logical set to 1 if trace must be terminated at new xyz
	- xyznew: XYZ object of new point of trace line
	- delt: extra time it takes to reach that point that cannot be
	computed from standard stepsize (for example leakage through resistance layer)
	'''
	def __init__(self,change=0,stop=0,xyzchanged=geometry.XYZ(0,0,0),delt=0):
		assert isinstance(xyzchanged,geometry.XYZ), "xyzchanged must be XYZ object"
		self.change = change
		self.stop = stop
		self.xyzchanged = xyzchanged
		self.delt = delt

class TraceLine:
	'''Object for storing a trace line

	Attributes:

	- xt: List of x locations
	- yt: List of y locations
	- zt: List of z locations
	- tt: List of time
	'''
	def __init__(self):
		self.xyzt = []
		self.tt = []
	def __repr__(self):
		for i in range(len(self.tt)):
			xyz = self.xyzt[i]; t = self.tt[i]
			print str((xyz.x,xyz.y,xyz.z,t))
		return str("end")
	def addpoint(self,xyznew,tnew):
		'''Adds point to object'''
		self.xyzt = self.xyzt + [xyznew]
		self.tt = self.tt + [tnew]
		return self
	def firstpoint(self):
		'''Returns first point'''
		if len(self.tt)>0:
			return (self.xyzt[0],self.tt[0])
	def lastpoint(self):
		'''Returns last point'''
		l = len(self.tt)
		if l>0:
			return (self.xyzt[l-1],self.tt[l-1])
	def appendtofile(self,file):
		'''Write object to file (appending it to existing contents)'''
		out = open(file,'a') # open file for appending
		out.write(str(len(self.xyzt))+' 1\n')
		for i in range(len(self.xyzt)):
			out.write(str(self.xyzt[i].x)+' '+str(self.xyzt[i].y)+'\n')
		out.close()
